#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <glut.h>
#include "string.h"

#ifdef WIN32
  #include <windows.h>
  unsigned long msecTime() { return (unsigned long)timeGetTime(); }
#endif

#ifdef UNIX
  #include <sys/time.h>

  static struct timeval tv;
  unsigned long msecTime()
  {
    gettimeofday(&tv,NULL);
    return (unsigned long)(tv.tv_sec * 1000 + (tv.tv_usec / 1000));
  }
#endif

float rotateX = 0.0f;
float rotateY = 0.0f;

char title[120];

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
      glTranslatef(0.0f, 0.0f, -5.0f);
      glRotatef(rotateX, 1, 0, 0);
      glRotatef(rotateY, 0, 1, 0);

      rotateX += 0.1f * (rand() % 10);
      rotateY += 0.1f * (rand() % 10);
      if (rotateX >= 360.0f) rotateX = 0.0f;
      if (rotateY >= 360.0f) rotateY = 0.0f;

      glutSolidCube(1.0f);
    glPopMatrix();
}

#define FPS 60.0f
int msecPerFrame = (int)(1000.0f / FPS);

unsigned long frames = 0,
              frameStart = -1,
              frameWait = -1,
              frameLast = -1;

unsigned long totalRenderTime = 0;
int pos = -1;

void updateFPS(unsigned long msec)
{
    totalRenderTime += msec;

  	if (totalRenderTime >= 1000)
    {
      if (pos == -1) pos = strlen(title);
  		sprintf(&title[pos], " - [FPS: %i]", frames);
      glutSetWindowTitle(title);

      totalRenderTime = 0;
      frames = 0;
  	}
}

void display()
{
    frameStart = msecTime();

    render();
    glutSwapBuffers();
    glutPostRedisplay();

    while ((frameWait = msecTime() - frameStart) < msecPerFrame) {}
    frameLast = frameWait;
    frames++;

    updateFPS(frameLast);
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, 1.333f, 0.1f, 10000.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

int main(int argc, char** argv)
{
    //memset(title, 0, sizeof(title);
    sprintf(title, "GLUT Program");

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(640, 480);

    glutCreateWindow(title);

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    //glutIdleFunc(idle);

    glutMainLoop();
    return EXIT_SUCCESS;
}
